﻿using System.Collections.Generic;
using System.Linq;
using Cms.Application.Admin.Views;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;

namespace Cms.Application.Admin.Presenters
{
    public class AdministratorGroupsPresenter : BasePresenter
    {
        private readonly Administrator _administrator;
        private readonly IAdministratorGroupsView _view;

        public AdministratorGroupsPresenter(IAdministratorGroupsView view)
            : this(view, new RepositoryFactory())
        {
        }

        public AdministratorGroupsPresenter(IAdministratorGroupsView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
            _administrator = AdministratorRepository.GetAdministrator(_view.AdministratorID);
            if (!_administrator.HasPermission.AdministratorGroups)
            {
                _view.RedirectToPermissionDeniedPage();
            }
        }

        public void Initialize()
        {
            SetGroups();
        }

        public void SetGroups()
        {
            _view.SetGroups(AdministratorRepository.GetGroups());
        }

        public void DeleteGroup(int id)
        {
            AdministratorGroup group = AdministratorRepository.GetGroup(id);
            if (group.Administrators.Count == 0)
            {
                PerformDelete(group);
            }
            else if (AdministratorRepository.GetGroups().Count > 1)
            {
                // Let user select an alternative group for the administrators in the current group
                IList<AdministratorGroup> replacements =
                    AdministratorRepository.GetGroups().Where(replacement => replacement.ID != id).ToList();
                _view.SetReplacements(replacements, group.Name);
            }
        }

        public void ReplaceAndDeleteGroup(int id, int replacementID)
        {
            AdministratorGroup group = AdministratorRepository.GetGroup(id);
            AdministratorGroup replacement;
            while (group.Administrators.Count > 0)
            {
                Administrator admin = group.Administrators[0];
                replacement = AdministratorRepository.GetGroup(replacementID);
                admin.Group = replacement;
                replacement.Administrators.Add(admin);
                group.Administrators.Remove(admin);
                AdministratorRepository.SaveAdministrator(admin);
                AdministratorRepository.SaveGroup(group);
                AdministratorRepository.SaveGroup(replacement);
            }
            PerformDelete(group);
        }
        
        private void PerformDelete(AdministratorGroup group)
        {
            // Clear references to pages
            foreach (Page page in group.AllowedPages)
            {
                page.AllowedAdministratorGroups.Remove(group);
            }
            group.AllowedPages.Clear();
            foreach (Page page in group.DeniedPages)
            {
                page.DeniedAdministratorGroups.Remove(group);
            }
            group.DeniedPages.Clear();

            // Clear references to folders
            foreach (Folder folder in group.AllowedFolders)
            {
                folder.AllowedAdministratorGroups.Remove(group);
            }
            group.AllowedFolders.Clear();
            foreach (Folder folder in group.DeniedFolders)
            {
                folder.DeniedAdministratorGroups.Remove(group);
            }
            group.DeniedFolders.Clear();
            
            // Clear references to mediafiles
            foreach (MediaFile file in group.AllowedMediaFiles)
            {
                file.AllowedAdministratorGroups.Remove(group);
            }
            group.AllowedMediaFiles.Clear();
            foreach (MediaFile file in group.DeniedMediaFiles)
            {
                file.DeniedAdministratorGroups.Remove(group);
            }
            group.DeniedMediaFiles.Clear();
            
            // Clear references to mediafolders
            foreach (MediaFolder folder in group.AllowedMediaFolders)
            {
                folder.AllowedAdministratorGroups.Remove(group);
            }
            group.AllowedMediaFolders.Clear();
            foreach (MediaFolder folder in group.DeniedMediaFolders)
            {
                folder.DeniedAdministratorGroups.Remove(group);
            }
            group.DeniedMediaFolders.Clear();
            
            // Clear references to content
            foreach (Content content in group.AllowedContent)
            {
                content.AllowedAdministratorGroups.Remove(group);
            }
            group.AllowedContent.Clear();
            foreach (Content content in group.DeniedContent)
            {
                content.DeniedAdministratorGroups.Remove(group);
            }
            group.DeniedContent.Clear();
            foreach (Permission permission in group.Permissions.Where(permission => permission.Groups.Contains(group)))
            {
                permission.Groups.Remove(group);
            }
            group.Permissions.Clear();

            // Save changes to remove references permanently
            AdministratorRepository.SaveGroup(group);
            
            // Delete the group
            AdministratorRepository.DeleteGroup(group.ID);
            SetGroups();
        }
    }
}